﻿namespace StreetCrime.Models
{
    using System;
    using Serialization;
    using WP7Contrib.Common;

    [Serializer(typeof(StreetLevelCrime))]
    public sealed class StreetLevelCrime : BaseModel, ISerializeObject, IEquatable<StreetLevelCrime>
    {
        private StreetLevelCrimeCategory category;

        private int id;

        private StreetLevelCrimeLocation location;

        private string context;

        private int month;

        private int year;

        public StreetLevelCrime()
        {
        }

        public object[] Serialize(object target)
        {
            var crime = (StreetLevelCrime)target;
            return new object[] { crime.Category,
                                  crime.Id,
                                  crime.Location,
                                  crime.Context,
                                  crime.Month,
                                  crime.Year };
        }

        public object Deserialize(object[] data)
        {
            var crime = new StreetLevelCrime
            {
                Category = (StreetLevelCrimeCategory)data[0],
                Id = (int)data[1],
                Location = (StreetLevelCrimeLocation)data[2],
                Context = (string)data[3],
                Month = (int)data[4],
                Year = (int)data[5]
            };

            return crime;
        }

        public StreetLevelCrimeCategory Category
        {
            get
            {
                return this.category;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.category, value, () => this.Category);
            }
        }

        public int Id
        {
            get
            {
                return this.id;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.id, value, () => this.Id);
            }
        }

        public StreetLevelCrimeLocation Location
        {
            get
            {
                return this.location;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.location, value, () => this.Location);
            }
        }

        public string Context
        {
            get
            {
                return this.context;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.context, value, () => this.Context);
            }
        }

        public int Month
        {
            get
            {
                return this.month;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.month, value, () => this.Month);
            }
        }

        public int Year
        {
            get
            {
                return this.year;
            }
            set
            {
                this.SetPropertyAndNotify(ref this.year, value, () => this.Year);
            }
        }

        public static bool operator ==(StreetLevelCrime slc1, StreetLevelCrime slc2)
        {
            return Equals(slc1, slc2);
        }

        public static bool operator !=(StreetLevelCrime slc1, StreetLevelCrime slc2)
        {
            return !Equals(slc1, slc2);
        }

        public bool Equals(StreetLevelCrime crime)
        {
            if (ReferenceEquals(null, crime))
            {
                return false;
            }

            if (this.Category != crime.Category)
            {
                return false;
            }

            if (this.Id != crime.Id)
            {
                return false;
            }

            if (this.Location != crime.Location)
            {
                return false;
            }

            if (this.Context != crime.Context)
            {
                return false;
            }

            if (this.Month != crime.Month)
            {
                return false;
            }

            if (this.Year != crime.Year)
            {
                return false;
            }

            return true;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }

            return obj is StreetLevelCrime && this.Equals((StreetLevelCrime)obj);
        }

        public override int GetHashCode()
        {
            return this.CombineHashCodes(this.Category, this.Context, this.Id, this.Location, this.Month, this.Year);
        }
    }
}